package com.itheima.project.handler.aliyun.impl;

import com.aliyun.oss.ClientException;
import com.aliyun.oss.OSS;
import com.aliyun.oss.OSSException;
import com.aliyun.oss.model.CannedAccessControlList;
import com.aliyun.oss.model.DeleteObjectsRequest;
import com.aliyun.oss.model.GetObjectRequest;
import com.aliyun.oss.model.ObjectMetadata;
import com.aliyun.oss.model.PutObjectRequest;
import com.aliyun.oss.model.PutObjectResult;
import com.google.common.io.ByteStreams;
import com.itheima.project.core.enums.file.FileEnum;
import com.itheima.project.exception.ExceptionCast;
import com.itheima.project.handler.AbsFileStorageHandler;
import com.itheima.project.handler.FileStorageHandler;
import com.itheima.project.handler.aliyun.properties.OssAliyunConfigProperties;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.stereotype.Service;
import org.springframework.util.StringUtils;

import java.io.IOException;
import java.io.InputStream;
import java.util.List;

/**
 * @ClassName OssFileStorageHandlerImpl.java
 * @Description 阿里云文件上传
 */
@Slf4j
@Service("ossFileStorageHandler")
@EnableConfigurationProperties(OssAliyunConfigProperties.class)
public class OssFileStorageHandlerImpl extends AbsFileStorageHandler implements FileStorageHandler {

    @Autowired
    OSS ossClient;

    @Autowired
    OssAliyunConfigProperties ossAliyunConfigProperties;

    /***
     * @description 文件元数据处理
     * @param prefix 文件后缀
     * @return
     */
    public ObjectMetadata fileMetaHandler(String prefix){
        //元数据对象
        ObjectMetadata objectMeta = new ObjectMetadata();
        //文件字符集
        objectMeta.setContentEncoding("UTF-8");
        //文件类型匹配
        objectMeta.setContentType(metaMimeTypeMap.get(prefix.toLowerCase()));
        return objectMeta;
    }

    @Override
    public String uploadFile(String suffix, String filename, String bucketName,boolean autoCatalog, InputStream inputStream) {
        String pathUrl = null;

        // 判断文件
        if (inputStream == null) {
            log.error("上传文件：存储文件key {}文件流为空", filename);
            ExceptionCast.cast(FileEnum.FILE_DATA_LOSE);
        }

        // 判断存储空间名称
        if (StringUtils.isEmpty(bucketName)) {
            log.error("存款空间的名称为空", filename);
            ExceptionCast.cast(FileEnum.BUCKET_NAME_NULL);
        }

        // 是否自动生成存储路径并设置文件路径和名称（Key）
        String key = null;
        if (autoCatalog) {
            key = builderOssPath(filename);
        } else {
            key = filename;
        }

        log.info("OSS文件上传开始：{}" ,key);
        try {
            // 上传文件元数据处理
            ObjectMetadata objectMeta = fileMetaHandler(suffix);
            //文件上传
            PutObjectRequest request = new PutObjectRequest(bucketName, key, inputStream,objectMeta);
            //上传限流
            if (ossAliyunConfigProperties.getIslimitSpeed()){
                request.setTrafficLimit(ossAliyunConfigProperties.getUplimitSpeed());
            }
            PutObjectResult result = ossClient.putObject(request);
            // 设置权限(公开读)
            ossClient.setBucketAcl(bucketName, CannedAccessControlList.PublicRead);
            if (result != null) {
                log.info("OSS文件上传成功：{}" , key);
                pathUrl = key.toString();
            }
        } catch (OSSException oe) {
            log.error("OSS文件上传错误：{}", oe);
            ExceptionCast.cast(FileEnum.UPLOAD_FAIL);
        } catch (ClientException ce) {
            log.error("OSS文件上传客户端错误：{}",ce);
            ExceptionCast.cast(FileEnum.UPLOAD_FAIL);
        }
        return pathUrl;
    }


    @Override
    public InputStream downloadFile(String bucketName,String pathUrl) throws IOException {
        GetObjectRequest request = new GetObjectRequest(bucketName, pathUrl);
        //下载传限流
        if (ossAliyunConfigProperties.getIslimitSpeed()){
            request.setTrafficLimit(ossAliyunConfigProperties.getDownlimitSpeed());
        }
        //ossObject包含文件所在的存储空间名称、文件名称、文件元信息以及一个输入流。
        InputStream inputStream =  ossClient.getObject(request).getObjectContent();
        return inputStream;
    }

    @Override
    public void delete(String bucketName,String pathUrl) {
        // 删除Objects
        ossClient.deleteObject(bucketName,pathUrl);
    }

    @Override
    public void deleteBatch(String bucketName,List<String> pathUrls) {
        // 删除Objects
        ossClient.deleteObjects(new DeleteObjectsRequest(bucketName).withKeys(pathUrls));
    }

    @Override
    public String getFileContent(String bucketName,String pathUrl) throws IOException {
        InputStream inputStream = downloadFile(bucketName,pathUrl);
        return new String(ByteStreams.toByteArray(inputStream));
    }
}
